/**
 * 
 */
package be.jaisy.osgi.console.service.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.ComponentContext;

import be.jaisy.osgi.console.service.api.IBundleManagementService;
import be.jaisy.osgi.console.service.api.to.BundleTo;
import be.jaisy.osgi.console.service.api.to.OsgiServiceTo;
import be.jaisy.osgi.console.service.internal.Activator;
import be.jaisy.osgi.console.service.util.ConsoleHelper;
import be.jaisy.osgi.exception.OSGIRuntimeException;

/**
 * @author Stany Blanvalet
 *
 */
public class BundleManagementServiceImpl implements IBundleManagementService {

	private BundleContext context;
	
	protected void activate(ComponentContext cc) {
		this.context = cc.getBundleContext();
	}

	protected void deactivate(ComponentContext context) throws Exception {
		this.context = null;
	}
	
	/* (non-Javadoc)
	 * @see be.jaisy.osgi.console.service.api.IBundleManagementService#listBundle()
	 */
	public Collection<BundleTo> listBundle() {
		if(context==null)
			throw new IllegalStateException("Service not yet initialized with ComponentContext");
		List<BundleTo> result = new ArrayList<BundleTo>();
		Bundle[] bundles = context.getBundles();
		for (Bundle bundle : bundles) {
			result.add(ConsoleHelper.convert(bundle));
		}
		
		Collections.sort(result, new Comparator<BundleTo>(){

			public int compare(BundleTo bundleTo1, BundleTo bundleTo2) {				
				if(bundleTo1.getBundleId()==null)
					return -1;
				return bundleTo1.getBundleId().compareTo(bundleTo2.getBundleId());
			}});
		
		return result;
	}
	
	/* (non-Javadoc)
	 * @see be.jaisy.osgi.console.service.api.IBundleManagementService#getBundle()
	 */
	public BundleTo getBundle(long bundleId) {
		if(context==null)
			throw new IllegalStateException("Service not yet initialized with ComponentContext");
		Bundle bundle = context.getBundle(bundleId);
		return ConsoleHelper.convert(bundle);
	}

	/* (non-Javadoc)
	 * @see be.jaisy.osgi.console.service.api.IBundleManagementService#startBundle(java.lang.String)
	 */
	public BundleTo startBundle(long bundleId){
		if(context==null)
			throw new IllegalStateException("Service not yet initialized with ComponentContext");
		Bundle bundle = context.getBundle(bundleId);
		if(bundle==null)
			throw new IllegalArgumentException("Bundle "+bundleId+" not installed");
		try {
			bundle.start();
		} catch (BundleException e) {
			Activator.logWarning(this.getClass(), "startBundle("+bundleId+") failed", e);
			throw new OSGIRuntimeException(e);
		}
		return ConsoleHelper.convert(bundle);
	}
	
	/* (non-Javadoc)
	 * @see be.jaisy.osgi.console.service.api.IBundleManagementService#stopBundle(java.lang.String)
	 */
	public BundleTo stopBundle(long bundleId){
		if(context==null)
			throw new IllegalStateException("Service not yet initialized with ComponentContext");
		Bundle bundle = context.getBundle(bundleId);
		if(bundle==null)
			throw new IllegalArgumentException("Bundle "+bundleId+" not installed");
		try {
			bundle.stop();
		} catch (BundleException e) {
			Activator.logWarning(this.getClass(), "stopBundle("+bundleId+") failed", e);
			throw new OSGIRuntimeException(e);
		}
		return ConsoleHelper.convert(bundle);
	}
	
	/* (non-Javadoc)
	 * @see be.jaisy.osgi.console.service.api.IBundleManagementService#updateBundle(java.lang.String)
	 */
	public BundleTo updateBundle(long bundleId){
		if(context==null)
			throw new IllegalStateException("Service not yet initialized with ComponentContext");
		Bundle bundle = context.getBundle(bundleId);
		if(bundle==null)
			throw new IllegalArgumentException("Bundle "+bundleId+" not installed");
		try {
			bundle.update();
		} catch (BundleException e) {
			Activator.logWarning(this.getClass(), "updateBundle("+bundleId+") failed", e);
			throw new OSGIRuntimeException(e);
		}		
		return ConsoleHelper.convert(bundle);
	}

	/* (non-Javadoc)
	 * @see be.jaisy.osgi.console.service.api.IBundleManagementService#installBundle(java.lang.String)
	 */
	public void installBundle(String location) {
		if(context==null)
			throw new IllegalStateException("Service not yet initialized with ComponentContext");
		try {
			this.context.installBundle(location);
		} catch (BundleException e) {
			Activator.logWarning(this.getClass(), "installBundle("+location+") failed", e);
			throw new OSGIRuntimeException(e);
		}	
	}

	/* (non-Javadoc)
	 * @see be.jaisy.osgi.console.service.api.IBundleManagementService#uninstallBundle(long)
	 */
	public BundleTo uninstallBundle(long bundleId) {
		if(context==null)
			throw new IllegalStateException("Service not yet initialized with ComponentContext");
		Bundle bundle = context.getBundle(bundleId);
		if(bundle==null)
			throw new IllegalArgumentException("Bundle "+bundleId+" not installed");
		try {
			bundle.uninstall();
		} catch (BundleException e) {
			Activator.logWarning(this.getClass(), "uninstallBundle("+bundleId+") failed", e);
			throw new OSGIRuntimeException(e);
		}	
		return ConsoleHelper.convert(bundle);
	}

	public Collection listRegisteredServices(long bundleId) {
		if(context==null)
			throw new IllegalStateException("Service not yet initialized with ComponentContext");
		Bundle bundle = context.getBundle(bundleId);
		if(bundle==null)
			throw new IllegalArgumentException("Bundle "+bundleId+" not installed");

		List<OsgiServiceTo> result = new ArrayList<OsgiServiceTo>();
		for (ServiceReference serviceReference : bundle.getRegisteredServices()) {
			result.add(ConsoleHelper.convert(serviceReference));
		}
		
		Collections.sort(result, new Comparator<OsgiServiceTo>(){

			public int compare(OsgiServiceTo osgiServiceTo1, OsgiServiceTo osgiServiceTo2) {				
				if(osgiServiceTo1.getDescription()==null)
					return -1;
				return osgiServiceTo1.getRegisteredBundleid().compareTo(osgiServiceTo1.getRegisteredBundleid());
			}});
		
		return result;
	}
}
